#ifndef ENTRIESMANAGER_H
#define ENTRIESMANAGER_H
#include <Entry.h>
#include<string>
#include<vector>
#include<stack>
#include <EntryManager.h>
#include <sstream>
#include <CommonUtils.h>
#include <algorithm>
#include <FileManager.h>
#include <assert.h>
#include <exception>
#include <BotException.h>
#include <assert.h>
#include <qmessagebox.h>
#include <libqxt-Qt5\include\QxtCore\qxtloggerengine.h>
#include <libqxt-Qt5\include\QxtCore\qxtlogger.h>
#include <libqxt-Qt5\include\QxtCore\QxtLogger>
#include <libqxt-Qt5\include\QxtCore\QxtBasicFileLoggerEngine>
#include <libqxt-Qt5\include\QxtCore\QxtBasicSTDLoggerEngine>
using namespace std;
class EntriesManager
{
	friend class EntriesManagerTest;
	friend class EntriesManagerUTest;
	
	enum DISPLAY_FORMAT{
		DISPLAY_DEFAULT,
		DISPLAY_SEARCH,
		DISPLAY_SEARCH_DATE
	};

	static const string _fileName;
	static const string STRING_NULL;
	static const QString FORMAT_DATE;
	static const QString FORMAT_TIME;
	static const string ENTRY_TYPE_EVENT;
	static const string ENTRY_TYPE_TASK;
	struct ENTRIES{
		vector<Entry*> activeEntries;
		vector<Entry*> inactiveEntries;
		vector<Entry*> conflictVector;
		DISPLAY_FORMAT currentDisplayFormat;
		//vector<vector<CommonUtils::ReturnString>> currentDisplay;
		Entry* newEntry;
		int currentDisplayIndex;
		QDate searchDate;
		string searchLabel;
	};
	ENTRIES _entries;
	stack<ENTRIES> _entriesHist;
	stack<ENTRIES> _entriesRedo;
	FileManager* _file;
	void sortByDate();
	enum MSG_TYPE{
		MSG_IS_EMPTY, 
		MSG_INVALID, 
		CONFLICT_ADD,
		SUCCESS_ADD, 
		SUCCESS_DELETE, 
		SUCCESS_DISPLAY, 
		SUCCESS_EDIT, 
		SUCCESS_CLEAR, 
		SUCCESS_SEARCH, 
		SUCCESS_SORT, 
		SUCCESS_UNDO, 
		SUCCESS_REDO, 
		SUCCESS_COMPLETED, 
		SUCCESS_GENERAL,
		SEARCH_NO_ITEMS
	};
	vector<vector<CommonUtils::ReturnString>> printVectorToString();
	vector<Entry*> getAllEntries();
	void splitVector(string, vector<Entry*>&, vector<Entry*>&, int searchType=0);
	void updateFile();
	void updateCurrentDisplayIndex();
	vector<Entry*> getConflict(Entry*);
	void deleteVector(vector<Entry*>&);
	
	void updateFoundEntries(const vector<Entry*>&, const vector<Entry*>&);
	void splitVectorTask(vector<Entry*>&, vector<Entry*>&);
	void splitVectorEvent(vector<Entry*>&, vector<Entry*>&);
	void splitVectorWeek(vector<Entry*>&, vector<Entry*>&);
	void splitVectorDay(QDate, vector<Entry*>&, vector<Entry*>&, int searchType=0);
	void splitVectorStatus(bool, vector<Entry*>&, vector<Entry*>&);
	void splitVectorBeforeDay(QDate, vector<Entry*>&, vector<Entry*>&);
	void generateNewVector();
	void clearRedoStack();
	void defaultSort();
	void clearOverflowUndo();
	CommonUtils::ReturnString getPastString(int);
	CommonUtils::ReturnString getTodayString(int);
	CommonUtils::ReturnString getFutureString(int);
	void filterStatus(bool=false);
	EntriesManager(FileManager* = NULL);
	static EntriesManager* _instance;
	bool isTask(Entry*);
	void setFormat(Entry*, CommonUtils::ReturnString&);
	void setDefaultDisplayHeader(vector<CommonUtils::ReturnString>&,vector<CommonUtils::ReturnString>&,vector<CommonUtils::ReturnString>&, vector<CommonUtils::ReturnString>&);
	void setSearchDisplayHeader(vector<CommonUtils::ReturnString>&);
	string printEventDateTime(Entry*);
	string printTaskDateTime(Entry*);
	string printTodayTaskDateTime(Entry*);
	string printTodayEventDateTime(Entry*);
	string printTodaySpanningEventDateTime(Entry*);
	void resetView();
	void showAll();
	void resetSearchAttributes();
	void convertTaskToEvent(Entry*&);
public:
	CommonUtils::ReturnCount getCount();

	static EntriesManager* getInstance(FileManager* = NULL);
	~EntriesManager(void);
	vector<vector<CommonUtils::ReturnString>> getDefaultString();
	vector<vector<CommonUtils::ReturnString>> getSearchString();
	vector<vector<CommonUtils::ReturnString>> getSearchDateString();
	CommonUtils::ReturnStatus addCommand(Entry*);
	CommonUtils::ReturnStatus deleteCommand(int);
	CommonUtils::ReturnStatus editCommand(int, vector<string>);
	CommonUtils::ReturnStatus displayCommand(bool = false);//false default, true to display all
	CommonUtils::ReturnStatus sortCommand();
	CommonUtils::ReturnStatus searchCommand(string, int searchType = 0);
	CommonUtils::ReturnStatus undoCommand();
	CommonUtils::ReturnStatus redoCommand();
	CommonUtils::ReturnStatus clearCommand();
	CommonUtils::ReturnStatus setDoneCommand(int);
	CommonUtils::ReturnStatus sendOutputMessage(string messageDisplayed, MSG_TYPE cmd);
	CommonUtils::ReturnStatus searchTasks();
	CommonUtils::ReturnStatus searchEvents();
	CommonUtils::ReturnStatus searchWeek();
	CommonUtils::ReturnStatus searchDay(QDate, int searchType=0);
	CommonUtils::ReturnStatus searchStatus(bool=0);
	bool guiEdit(int, int, QVariant);
	vector<Entry*> getActive();
	QStringList getNameVect();
};
#endif